package atom.core0.app.thread.daemon;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import atom.core0.app.thread.manager.DaemonThreadManager;
import atom.core0.global.GlobalCache;

/**
 * 主控服务线程
 * 
 * @author hike_man@126.com
 * 
 */
abstract public class BaseDaemonThread extends MyDaemonThread
{
	protected Logger	logger	 = Logger.getLogger("monitor");
	private String	  serverName	= "";

	protected int	  sleepGap	 = 1;
	protected boolean	bRun	 = true;
	protected boolean	bSuspend	= false;
	protected List<Class> continueExceptionList = new ArrayList();
	public BaseDaemonThread() {
		this.serverName = this.getClass().getSimpleName();
	}

	public void addContinueException(Class e)
	{
		continueExceptionList.add(e);
	}
	// doProcess 里面抛出异常将会退出
	abstract public void doProcess() throws InterruptedException, Exception;

	
	//返回true 继续;返回false终止
	abstract public boolean doProcessException(Throwable t);


	public void doInit() throws Exception
	{
		logger.info("轮询服务" + this.getName() + ",初始化Init");
	}

	public void doExit() throws Exception
	{
		logger.info("轮询服务" + this.getName() + ",正常退出Exit");
		DaemonThreadManager.remove(this);
	}

	public void setServerName(String strServerName, String serverClassName)
	{
		serverName = strServerName;
		return;
	}

	public String getServerName()
	{
		return serverName;
	}

	public void setServerName(String serverName)
	{
		this.serverName = serverName;
	}

	public void run()
	{


		this.setName(serverName);
		logger.info("轮询服务" + this.getName() + ",开始启动Start");
		try
		{
			doInit();
		}
		catch (Throwable t)
		{
			logger.info("轮询服务" + this.getName() + ",初始化异常退出Exit" + t.getMessage());
			return;
		}
		// 被标记中断 不再负责重新启动isInterrupted() 数据库断了呢？然后重新连接上，必须重新启动
		// sleep(),join(),wait() ，正常退出，都不再重新启动
		// 其它异常，尤其数据库异常，数据库断了呢？然后重新连接上，必须重新启动
		boolean bfirst = true;
		while (bRun || !isInterrupted())
		{
			try
			{
				// sleepGap 最低1秒
				if (!bfirst && sleepGap > 0)
				{
					logger.info("轮询服务" + this.getName() + ",正在运行,等候" + sleepGap + "秒...");
					Thread.sleep(1000 * sleepGap);
				}
				if (bfirst)
					bfirst = false;
				// 具体的服务线程在doProcess里面循环，不循环也可以，总之sleep要抛出InterruptedException异常
				if (!bRun)
				{
					logger.info("轮询服务" + this.getName() + ",被标记停止,服务准备退出...");
					break;
				}
				if (bSuspend)
				{
					logger.info("轮询服务" + this.getName() + ",处于暂停中Suspend...");
				}
				else
				{
					logger.info("轮询服务" + this.getName() + ",准备执行doProcess...");
					doProcess();
				}

				continue;
			}
			// sleep(),join(),wait() 都会中断
			catch (InterruptedException e)
			{
				logger.warn("轮询服务" + this.getName() + "被中断InterruptedException,服务准备退出");
				break;
			}
//			catch (CannotCreateTransactionException e)
//			{
//				logger.warn("轮询服务" + this.getName() + "遇到数据库连接异常1,稍后重连");
//				continue;
//			}
//			catch (TransactionSystemException e)
//			{
//				logger.warn("轮询服务" + this.getName() + "遇到数据库连接异常2,稍后重连");
//				continue;
//			}
			// 遇到其他异常 退出还是继续 由服务决定 默认退出 
			catch (Throwable t)
			{
				boolean bfit =false;
				for(int i=0;i<continueExceptionList.size();i++)
				{
					
					Class e = continueExceptionList.get(i);
					if (e.isInstance(t))
						bfit = true;;
				}
				if (bfit)
				{
					logger.warn("轮询服务" + this.getName() + "遇到异常,稍后重连"+t.getMessage());
					continue;
				}
				
				boolean ret = doProcessException(t);
				if (ret)
				{
					logger.warn ("轮询服务" + this.getName() + "继续运行,遇到错误[" + t.getMessage() + "]");
					continue;
				}
				else
				{
					logger.error("轮询服务" + this.getName() + "服务准备退出,原因[" + t.getMessage() + "]");
					logger.error(t.getMessage(), t);
					break;
				}
			}

		}
		try
		{
			doExit();
		}
		catch (Throwable t)
		{
			logger.error("轮询服务" + this.getName() + "退出时异常:" + t.getMessage());
			return;
		}
	}


	public int getSleepGap()
	{
		return sleepGap;
	}

	public void setSleepGap(int sleepGap)
	{
		this.sleepGap = sleepGap;
	}

	public boolean isRun()
	{
		return bRun;
	}

	public void setRun(boolean bRun)
	{
		this.bRun = bRun;
	}

	public boolean isSuspend()
	{
		return bSuspend;
	}

	public void setSuspend(boolean bSuspend)
	{
		this.bSuspend = bSuspend;
	}

	/*
	 * 1) t.interrupt()不会中断正在执行的线程，只是将线程的标志位设置成true。
	 * 但是如果线程在调用sleep(),join(),wait()方法时线程被中断，则这些方法会抛出InterruptedException，
	 * 在catch块中捕获到这个异常时，线程的中断标志位已经被设置成false了，
	 * 因此在此catch块中调用t.isInterrupted(),Thread.interrupted()始终都为false,
	 * 
	 * 测试线程是否已经中断。线程的中断状态 不受该方法的影响。
	 * 
	 * 如果该线程在可中断的通道上的 I/O 操作中受阻，则该通道将被关闭，该线程的中断状态将被设置并且该线程将收到一个
	 * ClosedByInterruptException。
	 * 
	 * 2) Thread.interrupted()假如当前的中断标志为true，则调完后会将中断标志位设置成false
	 * 测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说，如果连续两次调用该方法，则第二次调用将返回 false
	 */
}
